package other;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

import regexInput.DSList;
import regexInput.Node;


public class Scanner {

	private DSList struct;
	private boolean negatePart;
	private char[] negateString;
	private Node specs;
	private String text;
	private int textIndex;
	
	public Scanner(String path) throws IOException{
		negatePart = false;
		struct = new DSList();
		BufferedReader in = new BufferedReader(new FileReader(path));
		
		while (in.ready()) { 
			  textIndex = 0;
			  text = in.readLine();
			  Split();
			}
		
	}
	
	public void Split(){
		/**
		 * Reads one character at a time
		 * 
		 * */
		boolean gotName = false, gotSpecs = false, eol = false;	//eol = end of line
		char character;
		specs = new Node();
		String token = "";
				//Gets the Character Class Name
				while(textIndex < text.length() && gotName == false){
					character = getChar();
					if(token.equals("%%")){					//Find any comments and get rid of them
						textIndex = text.length();
						token = "";
					}
					if(character == ' ' && !token.equals("")){
						specs.setName(token);
						gotName = true;
					}
					else if(character == '\t'){					//Escape Character Combos
	
					}
					else if(character != ' '){					//Append to token (DO SPECAIL CASES HERE)
						token += character;
					}
				}
				
				token = "";
				
				//Takes the Specifications of Character Class
				while(textIndex < text.length() && gotSpecs == false){
					character = getChar();
					if(character == ' ' && !token.equals("")){
						if(token.equals("IN")){					//Keyword tells us to expect sub character class to follow
							gotSpecs = true;					//Done getting specs, move on
						}
					}
					//Found bracket
					else if(character == '['){
						while(peekChar() != ']'){	//Keep going until at the end bracket
							token += getChar();		//Consume character (the char after ] if just starting)
						}
						specs.addTheSpecs(analyzePart(token));
						getChar();
						token = "";												//Refresh token; completed one [] cycle
					}
					else if(character == '\t'){					//Escape Character Combos

					}
					else if(character != ' '){					//Append to token (DO SPECAIL CASES HERE IF ANY)
						token += character;
					}
			
				}
				
				token = "";
				
				//Describe any sub-Character Class keyword IN
				while(textIndex <= text.length() && gotSpecs == true){
					character = getChar();
					if(textIndex == text.length()){
						eol = true;
					}
					if(character == ' ' && !token.equals("")){	//Waits for sub Character Class name and takes care if falls through
						specs.setSubCharClass(token);
						textIndex = text.length() + 1;					//Quick End
					}
					else if(character == '\t'){					//Escape Character Combos

					}
					else if(character != ' '){					//Append to token (DO SPECAIL CASES HERE)
						token += character;
					}	
				}
				
				//Check if we got to end of line and there was something in token
				if(eol && !token.isEmpty()){
					specs.setSubCharClass(token);
				}
				
				//Do negation here!!!!!!!!!!!!!!!!!!
				
				//Stores information contained in specs (of type Node) into DSList
				if(gotName || gotSpecs){
					struct.addClass(specs);
				}
}
	
	private char getChar(){
		if(textIndex == text.length()){
			textIndex++;
			return (char) 0;
		}
		else{
			char thing;
			thing = text.charAt(textIndex);
			textIndex++;
			return thing;
		}
	}
	
	private char peekChar(){
		if(textIndex == text.length()){
			return (char) 0;
		}
		else{
			char thing;
			thing = text.charAt(textIndex);
			return thing;
		}
	}
	
	private char[] analyzePart(String part){
		int index = 0, indexString, count = 0;
		char[] charList = part.toCharArray();
		char[] charTemp;
		char character = part.charAt(0);
		String temp = "";
		while(index < charList.length){
			character = charList[index];
			if(character == '^'){					//Check negative
				negatePart = true;
			}
			if(character == '-'){								//Getting range of characters
				temp = getRangeOf(part.charAt(index - 1), part.charAt(index + 1));
				count = index;
				charTemp = new char[index - 1 + temp.length()];		//Copy paste the old part up to indexth slot into new array
					for(int i = 0; i < index; i++){
						charTemp[i] = charList[i];				
					}
					for(indexString = 1; indexString < temp.length(); indexString++){			//Put in the new stuff into array
						charTemp[count] = temp.charAt(indexString);
						count++;
					}
				charList = charTemp;
				index++;
			}
			else {
				charList[index] = character;
			}
			index++;
		}
		return charList;
	}
	
	private String getRangeOf(char begin, char terminate){
		//NOT HANDLING RANGE ERROR !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
		String charList;
		int start = begin;					//Get the starting point
		int count = start;					//Get inital value of range
		int end = terminate;				//Get the ending point
		charList = "";
		while(count < end + 1){							//Goes through all the valid characteres in range
			charList += (char) count;
			count++;
		}
		return charList;
	}
	public String toString(){
		return struct.toString();
	}
}
